package com.xuecheng.teaching.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CoursePubDTO;
import com.xuecheng.api.teaching.model.dto.*;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.teaching.WorkRecordCorrectionStatusEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.teaching.agent.CourseBaseApiAgent;
import com.xuecheng.teaching.agent.LearningApiAgent;
import com.xuecheng.teaching.common.constant.TeachingErrorCode;
import com.xuecheng.teaching.convert.CourseWorkRecConvert;
import com.xuecheng.teaching.convert.WordRecordConvert;
import com.xuecheng.teaching.convert.WorkConvert;
import com.xuecheng.teaching.convert.WorkRecordConvert;
import com.xuecheng.teaching.entity.CourseWorkRec;
import com.xuecheng.teaching.entity.Work;
import com.xuecheng.teaching.entity.WorkRecord;
import com.xuecheng.teaching.mapper.WorkRecordMapper;
import com.xuecheng.teaching.service.CourseWorkRecService;
import com.xuecheng.teaching.service.WorkRecordService;
import com.xuecheng.teaching.service.WorkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


/**
 * <p>
 * 作业提交记录 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class WorkRecordServiceImpl extends ServiceImpl<WorkRecordMapper, WorkRecord> implements WorkRecordService {

    @Autowired
    private CourseBaseApiAgent workApiAgent;

    @Autowired
    private CourseWorkRecService courseWorkRecService;

    @Autowired
    private WorkService workService;


    @Autowired
    private LearningApiAgent learningApiAgent;

    @Override
    public CourseWorkRecDTO readOverAll(Long companyId, String courseWorkId) {
        //判断关键数据
        if (ObjectUtils.isNull(companyId) || ObjectUtils.isNull(courseWorkId)) {
            ExceptionCast.cast(TeachingErrorCode.E_130507);
        }
        Long courseId = new Long(courseWorkId);
        //根据课程作业id获取课程作业提交信息
        CourseWorkRec courseWorkRec = courseWorkRecService.getById(courseId);
        if (ObjectUtils.isNull(courseWorkRec)) {
            ExceptionCast.cast(TeachingErrorCode.E_130508);
        }
        CourseWorkRecDTO courseWorkRecDTO = CourseWorkRecConvert.INSTANCE.entity2dto(courseWorkRec);
        courseWorkRecDTO.setCommitterNumber(courseWorkRecDTO.getAnswerNumber());
        //获取课程发布id
        Long coursePubId = courseWorkRecDTO.getCoursePubId();
        Integer count = learningApiAgent.getCount(coursePubId);
        courseWorkRecDTO.setLearnerNumber(count);

        //获取课程发布信息和课程计划信息
        LambdaQueryWrapper<WorkRecord> workRecordQuery = Wrappers.lambdaQuery(WorkRecord.class);
        workRecordQuery.eq(WorkRecord::getCoursePubId,coursePubId);

        //封装课程发布信息和课程计划信息
        List<WorkRecord> recGroups = this.list(workRecordQuery);
        ArrayList<RecGroupDTO> recGroupDTOS = new ArrayList<>();
        for (WorkRecord recGroup : recGroups) {
            RecGroupDTO recGroupDTO = new RecGroupDTO();
            recGroupDTO.setCoursePubId(recGroup.getCoursePubId());
            recGroupDTO.setTeachplanId(recGroup.getTeachplanId());
            recGroupDTO.setTeachplanName(recGroup.getTeachplanName());
            recGroupDTOS.add(recGroupDTO);
        }
        courseWorkRecDTO.setRecGroupDTOList(recGroupDTOS);


        for (RecGroupDTO recGroupDTO : recGroupDTOS) {
            Long teachplanId = recGroupDTO.getTeachplanId();
            LambdaQueryWrapper<WorkRecord> query = Wrappers.lambdaQuery(WorkRecord.class);
            query.eq(WorkRecord::getCoursePubId,coursePubId);
            query.eq(WorkRecord::getTeachplanId,teachplanId);
            List<WorkRecordDTO> dtos = WordRecordConvert.INSTANCE.entitys2dtos(this.list(query));
            recGroupDTO.setWorkRecordList(dtos);
        }

        return courseWorkRecDTO;
    }

    @Transactional
    public WorkRecordDTO createOrWorkRecord(WorkRecordDTO workRecordDTO, String username) {
        //1.判断关键数据: 作业id  作业发布id  课程计划id  计划名称   学员名称
        Long workId = workRecordDTO.getWorkId();
        if (
                ObjectUtils.isEmpty(workId) ||
                        ObjectUtils.isEmpty(workRecordDTO.getCoursePubId()) ||
                        ObjectUtils.isEmpty(workRecordDTO.getTeachplanId()) ||
                        ObjectUtils.isEmpty(workRecordDTO.getTeachplanName()) ||
                        StringUtils.isEmpty(username)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //根据课程发布id查找coursePub课程信息
        RestResponse<CoursePubDTO> response = workApiAgent.getByCourse4s(workRecordDTO.getCoursePubId());
        if (!response.isSuccessful()) {
            ExceptionCast.cast(CommonErrorCode.E_999981);
        }
        //根据课程发布标识获取课程信息并判断状态（只能是已发布和使用）
        CoursePubDTO coursePubDTO = response.getResult();
        if (ObjectUtils.isEmpty(coursePubDTO)) {
            ExceptionCast.cast(CommonErrorCode.E_999981);
        }

        //判断学员对应的作业是否存在
        LambdaQueryWrapper<WorkRecord> workRecordWrapper = new LambdaQueryWrapper<>();
        workRecordWrapper.eq(WorkRecord::getUsername, username);
        workRecordWrapper.eq(WorkRecord::getWorkId, workId);
        workRecordWrapper.eq(WorkRecord::getCoursePubId, coursePubDTO.getId());
        WorkRecord workRecord = this.getOne(workRecordWrapper);
        WorkRecordDTO workRecordResult = null;
        //不存在则创建作业
        if (ObjectUtils.isEmpty(workRecord)) {
            workRecordResult = createWorkRecord(workRecordDTO, username);
        } else {
            //存在修改作业
            workRecordResult = modifyWorkRecord(workRecordDTO, username);
        }
        return workRecordResult;
    }


    //添加学员作业记录
    private WorkRecordDTO createWorkRecord(WorkRecordDTO workRecordDTO, String username) {
        WorkRecord workRecord = new WorkRecord();

        //添加各个数据
        workRecord.setUsername(username);
        workRecord.setWorkId(workRecordDTO.getWorkId());
        Work work = workService.getById(workRecordDTO.getWorkId());
        workRecord.setCoursePubId(workRecordDTO.getCoursePubId());
        workRecord.setTeachplanId(workRecordDTO.getTeachplanId());
        workRecord.setTeachplanName(workRecordDTO.getTeachplanName());
        workRecord.setAnswer(workRecordDTO.getAnswer());
        workRecord.setCorrectComment(workRecordDTO.getCorrectComment());
        workRecord.setCreateDate(workRecordDTO.getCreateDate());
        workRecord.setQuestion(work.getQuestion());
        workRecord.setStatus(WorkRecordCorrectionStatusEnum.RECORD_CORRECT_PENDING.getCode());
        boolean saveResult = this.save(workRecord);
        if (!saveResult) {
            ExceptionCast.cast(TeachingErrorCode.E_130412);
        }

        //修改course_work_rect中答题人数和待批阅数加1
        LambdaQueryWrapper<CourseWorkRec> courseWorkRecQueryWrapper = new LambdaQueryWrapper<>();
        courseWorkRecQueryWrapper.eq(CourseWorkRec::getCoursePubId, workRecordDTO.getCoursePubId());
        CourseWorkRec courseWorkRec = courseWorkRecService.getOne(courseWorkRecQueryWrapper);
        LambdaUpdateWrapper<CourseWorkRec> courseWorkRecUpdateWrapper = new LambdaUpdateWrapper<>();
        courseWorkRecUpdateWrapper.eq(CourseWorkRec::getCoursePubId, workRecordDTO.getCoursePubId());
        courseWorkRecUpdateWrapper.set(CourseWorkRec::getAnswerNumber, courseWorkRec.getAnswerNumber() + 1);
        courseWorkRecUpdateWrapper.set(CourseWorkRec::getTobeReviewed, courseWorkRec.getTobeReviewed() + 1);
        boolean update = courseWorkRecService.update(courseWorkRecUpdateWrapper);
        if (!update) {
            ExceptionCast.cast(TeachingErrorCode.E_130413);
        }

        WorkRecord record = this.getById(workRecord);
        WorkRecordDTO dto = WordRecordConvert.INSTANCE.entity2dto(record);
        return dto;


    }

    //修改学员作业记录workRecord
    private WorkRecordDTO modifyWorkRecord(WorkRecordDTO workRecordDTO, String username) {

        WorkRecord workRecord = WordRecordConvert.INSTANCE.dto2entity(workRecordDTO);

        boolean result = this.updateById(workRecord);
        if (!result) {
            ExceptionCast.cast(TeachingErrorCode.E_130404);
        }
        WorkRecord po = this.getById(workRecordDTO.getWorkRecordId());
        WorkRecordDTO dto = WordRecordConvert.INSTANCE.entity2dto(po);
        return dto;
    }

    /*
     *作业批改意见提交
     *         开启事务
     *     1.判断关键数据
     *          WorkRecordId CorrectComment
     *     2. 判断业务数据
     *              判断作业内容是否存在
     *                  作业内容状态是否为 待批改--306002
     *              判断作业是否存在
     *                  是否删除
     *                  是否是同一家机构
     *                  是否绑定课程计划 远程调用
     *      3. 修改作业批阅增量计数
     *                  判断待批阅数是否为0
     *                       不为0  ：tobe_reviewed 待批阅数 -1
     *                                reviewed_time 最后批阅时间
     *                        为0 ： 报异常
     *      4 . 判断是否修改成功
     *      5. 修改作业记录状态 "306003", "已批改
     *                   批改意见
     *                   批改时间
     *                   修改时间
     *       6 . 判断是否修改成功
     *       7. 查询最新作业记录
     *       8. po转换dto
     *       9. 返回数据
     */

    @Transactional  //开启事务
    public WorkRecordDTO submitWorkRecord(WorkRecordDTO workRecordDTO, Long companyId) {
        //1.判断关键数据   WorkRecordId CorrectComment
        if (ObjectUtils.isEmpty(workRecordDTO.getCorrectComment()) ||
                ObjectUtils.isEmpty(workRecordDTO.getWorkRecordId())) {
            ExceptionCast.cast(TeachingErrorCode.E_130601);
        }
        // 2. 判断业务数据
        //2.2 判断作业内容是否存在 ,状态是否为 待批改--306002
        //       构建LambdaQueryWrapper条件查询
        LambdaQueryWrapper<WorkRecord> workRecordQueryWrapper = new LambdaQueryWrapper<>();
        //      添加查询条件
        workRecordQueryWrapper.eq(WorkRecord::getId, workRecordDTO.getWorkRecordId())
                .eq(WorkRecord::getStatus, WorkRecordCorrectionStatusEnum.RECORD_CORRECT_PENDING.getCode());
        //       查询
        WorkRecord workRecord = this.getOne(workRecordQueryWrapper);
        //       判断是否存在
        if (ObjectUtils.isEmpty(workRecord)) {
            ExceptionCast.cast(TeachingErrorCode.E_130407);
        }
        // 2 .1判断作业是否存在 是否删除 是否是同一家机构
        //获取workId
        Long workId = workRecord.getWorkId();
        //     构建LambdaQueryWrapper条件查询
        LambdaQueryWrapper<Work> workQueryWrapper = new LambdaQueryWrapper<>();
        //     添加查询条件
        workQueryWrapper.eq(Work::getId, workId)
                .eq(Work::getStatus, CommonEnum.USING_FLAG.getCode())
                .eq(Work::getCompanyId, companyId);
        //     查询数量
        Work work = workService.getOne(workQueryWrapper);
        //     判断数量
        if (ObjectUtils.isEmpty(work)) {
            ExceptionCast.cast(TeachingErrorCode.E_130603);
        }
        //     判断是否绑定课程计划--远程调用
        RestResponse<List<TeachplanWorkDTO>> restResponse = workApiAgent.getByWorkId4s(workId);
        if (!(restResponse.isSuccessful())) {
            ExceptionCast.cast(TeachingErrorCode.E_130401);
        }

        // 3. 修改作业批阅增量计数
        // course_work_rec表 tobe_reviewed 待批阅数 -1  ,   reviewed_time 最后批阅时间
        //       构建LambdaQueryWrapper条件查询
        LambdaQueryWrapper<CourseWorkRec> courseWorkRecQueryWrapper = new LambdaQueryWrapper<>();
        //    添加修改条件
        courseWorkRecQueryWrapper.eq(CourseWorkRec::getCoursePubId,workRecord.getCoursePubId());
        //    获取批阅增量计数表
        CourseWorkRec courseWorkRec = courseWorkRecService.getOne(courseWorkRecQueryWrapper);
        //   构建LambdaUpdateWrapper查询
        Integer tobeReviewed = courseWorkRec.getTobeReviewed();
        LambdaUpdateWrapper<CourseWorkRec> courseWorkRecUpdateWrapper = new LambdaUpdateWrapper<>();
        //    添加修改条件
        courseWorkRecUpdateWrapper.eq(CourseWorkRec::getCoursePubId, workRecord.getCoursePubId());
        boolean update = true;
        //判断待批阅数是否为0
        if (tobeReviewed > 0) {
            //不为0，待批阅数-1
            courseWorkRecUpdateWrapper.set(CourseWorkRec::getTobeReviewed, courseWorkRec.getTobeReviewed() - 1)
                    .set(CourseWorkRec::getReviewedTime, LocalDateTime.now());
            update = courseWorkRecService.update(courseWorkRecUpdateWrapper);
        } else {
            //为0，报异常
            ExceptionCast.cast(TeachingErrorCode.E_130413);
        }
        //判断是否修改成功
        if (!update) {
            ExceptionCast.cast(TeachingErrorCode.E_130412);
        }
        //5. 修改作业记录状态 "306003", "已批改  批改意见 批改时间  修改时间
        //      构建LambdaUpdateWrapper查询
        LambdaUpdateWrapper<WorkRecord> wrUpdateWrapper = new LambdaUpdateWrapper<>();
        //添加修改条件
        wrUpdateWrapper.eq(WorkRecord::getId, workRecordDTO.getWorkRecordId())
                .set(WorkRecord::getStatus, WorkRecordCorrectionStatusEnum.RECORD_CORRECT_PENDED.getCode())
                .set(WorkRecord::getCorrectComment, workRecordDTO.getCorrectComment())
                .set(WorkRecord::getCorrectionDate, LocalDateTime.now())
                .set(WorkRecord::getChangeDate, LocalDateTime.now());
        //  修改课程信息
        boolean wrupdate = this.update(wrUpdateWrapper);
        //  判断是否修改成功
        if (ObjectUtils.isEmpty(wrupdate)) {
            ExceptionCast.cast(TeachingErrorCode.E_130404);
        }
        //7. 查询最新作业记录
        WorkRecord po = this.getById(workRecordDTO.getWorkRecordId());
        //8. po转换为dto
        WorkRecordDTO dto = WorkRecordConvert.INSTANCE.entity2dto(po);
        return dto;
    }

    /*
     *根据workId查询课程计划作业填写请况
     *  1. 判断关键数据 workId  companyId username
     *  2. 判断业务数据
     *        判断作业：是否存在，是否是同一家机构，是否删除 使用态--1
     *        判断存储学生提交(回答)的作业内容
     *                 是否存在 是否同一提交人
     *                      存在：将po转换为dto
     *                            返回dto
     *                      不存在 添加数据信息
     * 3.返回数据
     */
    public WorkDTO queryWorkRecord(Long workId, String username) {
        //1. 判断关键数据
        if (ObjectUtils.isEmpty(workId) ||
                StringUtil.isBlank(username)) {
            ExceptionCast.cast(TeachingErrorCode.E_130601);
        }
        //2. 判断业务数据
        // 2.1 判断作业：是否存在，是否是同一家机构，是否删除 使用态--1
        //     构建LambdaQueryWrapper条件对象
        LambdaQueryWrapper<Work> workQueryWrapper = new LambdaQueryWrapper<>();
        //     添加查询条件
        workQueryWrapper.eq(Work::getId, workId)
                .eq(Work::getStatus, CommonEnum.USING_FLAG.getCode());
        //      查询数量
        Work work = workService.getOne(workQueryWrapper);
        //判断查询数量是否存在
        if (ObjectUtils.isEmpty(work)) {
            ExceptionCast.cast(TeachingErrorCode.E_130603);
        }
        WorkDTO workDTO = WorkConvert.INSTANCE.entity2dto(work);
        return workDTO;
    }

    // 内容管理远程调用-teaching:创建courseWorkRec表
    @Transactional
    public void createCourseWorkRecByCourseId(CoursePubDTO dto, Integer count) {

        CourseWorkRec courseWorkRec = new CourseWorkRec();
        courseWorkRec.setCompanyId(dto.getCompanyId());
        courseWorkRec.setCoursePubId(dto.getId());
        courseWorkRec.setCourseName(dto.getName());
        //作业总数
        courseWorkRec.setWorkNumber(count);
        //答题人数
        courseWorkRec.setAnswerNumber(0);
        //待批阅数
        courseWorkRec.setTobeReviewed(0);
        boolean result = courseWorkRecService.save(courseWorkRec);
        if (!result) {
            ExceptionCast.cast(TeachingErrorCode.E_130414);
        }
    }
}
